/*****************************************************************************/
/**
 *  @file   WriteSubDividedAVSFields.cpp
 *  @author Naohisa Sakamoto
 */
/*----------------------------------------------------------------------------
 *
 *  Copyright (c) Visualization Laboratory, Kyoto University.
 *  All rights reserved.
 *  See http://www.viz.media.kyoto-u.ac.jp/kvs/copyright/ for details.
 *
 *  $Id$
 */
/*****************************************************************************/
#include "WriteSubDividedAVSFields.h"
#include <kvs/Vector3>
#include <kvs/AnyValueArray>
#include <sstream>


namespace kvsbloodvis
{

namespace util
{

/*===========================================================================*/
/**
 *  @brief  Writes subdived AVS field files.
 *  @param  avs [in] AVS field data
 *  @param  basename [in] basename of the output file name
 *  @param  ndivs [in] number of subdivisions
 */
/*===========================================================================*/
void WriteSubDividedAVSFields( const kvs::AVSField& avs, const std::string& basename, size_t ndivs )
{
    const size_t veclen = avs.veclen();
    if ( veclen == 1 )
    {
        const kvs::Vector3ui resolution = avs.dim();
        const kvs::AnyValueArray values = avs.values();
        const size_t dimx = resolution.x() / ndivs;
        const size_t dimy = resolution.y();
        const size_t dimz = resolution.z();
        for ( size_t index = 0; index < ndivs; index++ )
        {
            kvs::ValueArray<kvs::UInt8> div_values( dimx * dimy * dimy );
            for ( size_t k = 0, K = 0; k < dimz; k++, K++ )
            {
                for ( size_t j = 0, J = 0; j < dimy; j++, J++ )
                {
                    for ( size_t i = 0, I = dimx * index; i < dimx; i++, I++ )
                    {
                        const size_t div_values_index = k * dimx * dimy + j * dimx + i;
                        const size_t values_index = K * resolution.x() * resolution.y() + J * resolution.x() + I;
                        div_values[ div_values_index ] = values.at<kvs::UInt8>( values_index );
                    }
                }
            }

            std::ostringstream oss;
            oss.setf( std::ios::right );
            oss.fill( '0' );
            oss.width( 5 );
            oss << index;
            std::string number = oss.str();

            kvs::AVSField div_avs;
            div_avs.setBits( 8 );
            div_avs.setSigned( false );
            div_avs.setVeclen( 1 );
            div_avs.setNSpace( 3 );
            div_avs.setNDim( 3 );
            div_avs.setDim( kvs::Vector3ui( dimx, dimy, dimz ) );
            div_avs.setFieldType( kvs::AVSField::Uniform );
            div_avs.setDataType( kvs::AVSField::Byte );
            div_avs.setValues( div_values );
            div_avs.write( basename + "_" + number + ".fld" );
            div_avs.print( std::cout << std::endl );
        }
    }
    else if ( veclen == 3 )
    {
        const kvs::Vector3ui resolution = avs.dim();
        const kvs::AnyValueArray values = avs.values();
        const size_t dimx = resolution.x() / ndivs;
        const size_t dimy = resolution.y();
        const size_t dimz = resolution.z();
        for ( size_t index = 0; index < ndivs; index++ )
        {
            kvs::ValueArray<kvs::Real32> div_values( dimx * dimy * dimy * veclen );
            for ( size_t k = 0, K = 0; k < dimz; k++, K++ )
            {
                for ( size_t j = 0, J = 0; j < dimy; j++, J++ )
                {
                    for ( size_t i = 0, I = dimx * index; i < dimx; i++, I++ )
                    {
                        const size_t div_values_index = k * dimx * dimy + j * dimx + i;
                        const size_t values_index = K * resolution.x() * resolution.y() + J * resolution.x() + I;
                        for ( size_t v = 0; v < veclen; v++ )
                        {
                            div_values[ veclen * div_values_index + v ] = values.at<kvs::Real32>( veclen * values_index + v );
                        }
                    }
                }
            }

            std::ostringstream oss;
            oss.setf( std::ios::right );
            oss.fill( '0' );
            oss.width( 5 );
            oss << index;
            std::string number = oss.str();

            kvs::AVSField div_avs;
            div_avs.setBits( 32 );
            div_avs.setSigned( true );
            div_avs.setVeclen( 3 );
            div_avs.setNSpace( 3 );
            div_avs.setNDim( 3 );
            div_avs.setDim( kvs::Vector3ui( dimx, dimy, dimz ) );
            div_avs.setFieldType( kvs::AVSField::Uniform );
            div_avs.setDataType( kvs::AVSField::Float );
            div_avs.setValues( div_values );
            div_avs.write( basename + "_" + number + ".fld" );
            div_avs.print( std::cout << std::endl );
        }
    }
}

} // end of namespace util

} // end of namespace kvsbloodvis
